package com.ymatou.iapi.settlement.testcase;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import com.ymatou.iapi.optrade.parameter.enums.AuthenticateFeeTypeEnum;
import com.ymatou.iapi.optrade.parameter.enums.AuthenticateFreightTypeEnum;
import com.ymatou.iapi.optrade.parameter.enums.LogisticsTypeEnum;
import com.ymatou.iapi.optrade.parameter.req.AgreeRefundReq;
import com.ymatou.iapi.optrade.parameter.req.ApplyRefundReq;
import com.ymatou.iapi.optrade.parameter.req.PlaceOrderReq;
import com.ymatou.iapi.optrade.parameter.vo.OrderGroupVo;
import com.ymatou.iapi.optrade.parameter.vo.OrderItemVo;
import com.ymatou.iapi.optrade.parameter.vo.OrderVo;
import com.ymatou.iapi.optrade.parameter.vo.SalesRefundInfoVo;
import com.ymatou.iapi.optrade.resp.Order;
import com.ymatou.iapi.optrade.resp.TradingServiceResp;
import com.ymatou.iapi.optrade.service.AgreeRefundCall;
import com.ymatou.iapi.optrade.service.RefundService;
import com.ymatou.iapi.settlement.parameter.GenerateRefundCommissionInvoiceBean;
import com.ymatou.iapi.settlement.parameter.OrderSettlementReq;
import com.ymatou.iapi.settlement.parameter.SettleSellerIncomeAndChargeCommissionBean;
import com.ymatou.iapi.settlement.service.GenerateInvoicesOnOrderReceivedCall;
import com.ymatou.iapi.settlement.service.GenerateRefundCommissionInvoiceCall;
import com.ymatou.iapi.settlement.service.SettleSellerIncomeAndChargeCommissionCall;
import com.ymatou.iapi.settlement.service.SettlementService;
import com.ymatou.iapi.synctrade.service.TradingSyncService;
import com.ymt.core.tool.Logger;
import com.ymt.utils.annotation.TestCase;
import com.ymt.utils.annotation.TestSuite;
import com.ymt.utils.tag.P1;
import com.ymttest.business.service.JUserCallService;
import com.ymttest.business.service.OrderCallService;
import com.ymttest.business.service.PayGateWayCallService;
import com.ymttest.business.service.YMTTrading.TradingCallService;
import com.ymttest.business.service.YMTTrading.TradingPlaceAuthenticateCallService;
import com.ymttest.business.service.YMTTrading.TradingPlaceOrderCallService;
import com.ymttest.business.service.YMTTrading.TradingProductVo;
import com.ymttest.common.order.userquery.util.Utils;
import com.ymttest.database.model.Account;
import com.ymttest.database.model.YmtCommissionDetail;
import com.ymttest.database.sharding.db.sharding.model.RefundBillPo;
import com.ymttest.database.sharding.db.sqlwapper.OrderShardingWapper;
import com.ymttest.database.sqlwapper.AccountWapper;
import com.ymttest.database.sqlwapper.DefaultWapper;
import com.ymttest.database.sqlwapper.YmtCommissionDetailWapper;
import com.ymttest.utils.EnvSetup;

/**
 * 生成确认收货之后的退货退款所引起的退佣结算单接口 FreeMaker Template自动生成代码
 */
@TestSuite
public class Ts_GenerateRefundCommissionInvoice {

	private static GenerateRefundCommissionInvoiceBean generaterefundcommissioninvoiceBean;
	private static GenerateRefundCommissionInvoiceCall generaterefundcommissioninvoiceCall;

	private static OrderSettlementReq generateinvoicesonorderreceivedBean;
	private static GenerateInvoicesOnOrderReceivedCall generateinvoicesonorderreceivedCall;

	private static SettleSellerIncomeAndChargeCommissionBean settlesellerincomeandchargecommissionBean;
	private static SettleSellerIncomeAndChargeCommissionCall settlesellerincomeandchargecommissionCall;
	
	private static AgreeRefundReq salesrefundsuccessReq = new AgreeRefundReq();
	private static AgreeRefundCall salesrefundsuccessCall = new AgreeRefundCall();
	
	private static OrderShardingWapper orderShardingWapper = new OrderShardingWapper();

	@BeforeClass
	public static void setUp() {
		Logger.createResultFile("生成确认收货后的退货退款所引起的退佣结算单接口");
	}

	@Before
	public void caseUp() {

		generaterefundcommissioninvoiceBean = new GenerateRefundCommissionInvoiceBean();
		generaterefundcommissioninvoiceCall = new GenerateRefundCommissionInvoiceCall();

		generateinvoicesonorderreceivedBean = new OrderSettlementReq();
		generateinvoicesonorderreceivedCall = new GenerateInvoicesOnOrderReceivedCall();

		settlesellerincomeandchargecommissionBean = new SettleSellerIncomeAndChargeCommissionBean();
		settlesellerincomeandchargecommissionCall = new SettleSellerIncomeAndChargeCommissionCall();

	}

	@AfterClass
	public static void tearDown() {
		Logger.generateResult(generaterefundcommissioninvoiceCall.getOpurl());
		orderShardingWapper.activeDeadCommunicationsLink(orderShardingWapper);
	}

	@After
	public void caseDown() {
		Logger.end();
	}

	/**
	 * 一个订单下面多个商品
	 * @throws Exception 
	 */
	@SuppressWarnings({ "rawtypes", "static-access" })
	private TradingServiceResp placeOrder(boolean isFreightFree)
			throws Exception {

		// 注册新用户
		Map newUser = new HashMap();
		newUser = new OrderCallService().registerUser();

		int userId = (Integer) newUser.get("userId");
		int sellerId = Integer.valueOf(EnvSetup.getData("autotest_seller1"));
		String sellerName = new JUserCallService().GetUserInfo(sellerId)
				.getLoginId();

		PlaceOrderReq placeorderBean = TradingCallService
				.buildStandPlaceOrderReq();
		
		OrderGroupVo orderGroupVo = TradingCallService.createOrderGroupVo(sellerId, sellerName);
		OrderVo orderVo = TradingCallService.createOrderVo();
		
		TradingProductVo productVo1 = TradingProductVo.createPro((long) sellerId, sellerName,
				10);
		TradingProductVo productVo2 = TradingProductVo.createPro(
				(long) sellerId, sellerName, 10);
		
		OrderItemVo orderItemVo1 = TradingCallService.createOrderItemVo(
				productVo1.getProductId(), productVo1.getCatalogId());
		OrderItemVo orderItemVo2 = TradingCallService.createOrderItemVo(
				productVo2.getProductId(), productVo2.getCatalogId());
		
		// 第二个商品价格设置一个大金额，佣金收费超过最大150阀值
		orderItemVo2.setProductPrice(new BigDecimal(3100));
		orderItemVo2.setOriginalPrice(new BigDecimal(3100));
		
		orderVo.setOrderItems(Arrays.asList(orderItemVo1, orderItemVo2));
		orderVo.setLogisticsType(LogisticsTypeEnum.OVERSEAS_DELIVERY);

		int firstCataid = 1149;

		// 设置没有商品的随机运费
		for (int i = 0; i < 1; i++) {
			for (int j = 0; j < 1; j++) {
				placeorderBean
						.getOrderGroups()
						.get(i)
						.getOrders()
						.get(j)
						.getOrderItems()
						.forEach(
								item -> {

									if (!isFreightFree) {

										item.setFreight(new BigDecimal(
												new Random().nextInt(50)));
									}
									item.setFirstCategoryId(firstCataid);
								});
			}
		}
		
		orderGroupVo.setOrders(Arrays.asList(orderVo));
		
		placeorderBean.setOrderGroups(Arrays.asList(orderGroupVo));
		placeorderBean.setUserId(userId);
		placeorderBean.setOrderGroups(Arrays.asList(TradingCallService
				.createOrderGroupVo(sellerId, sellerName)));

		return TradingCallService.callPlaceOrderService(placeorderBean);
	}
	
//	/**
//	 * 商品部分退款
//	 * 
//	 * @param orderId
//	 * @param money 部分退款金额
//	 * @param orderCallService
//	 * @return refundBillNo
//	 * @throws ClientProtocolException
//	 * @throws IOException
//	 */
//	private String partRefund(int orderId, int money,
//			OrderCallService orderCallService) throws ClientProtocolException,
//			IOException {
//		// 申请部分退款
//		ApplySalesRefundRequestBean applysalesrefundrequestBean = orderCallService
//				.applySalesRefundRequestInJavaBean(orderId);
//		String refundBillNo = applysalesrefundrequestBean
//				.getSalesRefundInfoList().get(0).getRefundBillNo();
//		String CatalogId = applysalesrefundrequestBean.getSalesRefundInfoList()
//				.get(0).getCatalogId();
//		String OrderInfoId = (String) new DefaultWapper()
//				.selectOrderInfoByOderId(orderId).stream()
//				.filter(a -> a.get("sCatalogId").equals(CatalogId))
//				.collect(Collectors.toList()).get(0).get("sOrderInfoId");
//		BigDecimal CommissionPerProd = calcCommissionPerProd(OrderInfoId);
//		applysalesrefundrequestBean.getSalesRefundInfoList().get(0)
//				.setRefundAmount(CommissionPerProd.add(new BigDecimal(money)));
//		ApplySalesRefundRequestCall applysalesrefundrequestCall = new ApplySalesRefundRequestCall();
//		applysalesrefundrequestCall.setData(false, applysalesrefundrequestBean);
//		applysalesrefundrequestCall.callService();
//
//		// 退款处理
//		orderCallService.salesrefundsuccessrequest(applysalesrefundrequestBean);
//		return refundBillNo;
//	}

	/**
	 * 计算期望的单件商品实际支付金额
	 * 
	 * @param orderInfoId
	 * @return
	 */
//	private BigDecimal calcCommissionPerProd(String orderInfoId) {
//
//		BigDecimal payAmount = BigDecimal.ZERO;
//
//		DefaultWapper defaultWapper = new DefaultWapper();
//
//		List<Map> ymtOrderInfoList = defaultWapper
//				.selectOrderInfoByOrderInfoId(orderInfoId);
//
//		BigDecimal fProductPrice = (BigDecimal) ymtOrderInfoList.get(0).get(
//				"fProductPrice");
//		int iAmount = (Integer) ymtOrderInfoList.get(0).get("iAmount");
//
//		BigDecimal fDiscount = (BigDecimal) ymtOrderInfoList.get(0).get(
//				"fDiscount");
//		BigDecimal fFreight = (BigDecimal) ymtOrderInfoList.get(0).get(
//				"fFreight");
//		BigDecimal fSellerPromotionAmount = (BigDecimal) ymtOrderInfoList
//				.get(0).get("fSellerPromotionAmount");
//		BigDecimal fSellerCouponAmount = (BigDecimal) ymtOrderInfoList.get(0)
//				.get("fSellerCouponAmount");
//		BigDecimal fYmtCouponAmount = (BigDecimal) ymtOrderInfoList.get(0).get(
//				"fYmtCouponAmount");
//
//		payAmount = fProductPrice.multiply(new BigDecimal(iAmount))
//				.add(fDiscount).add(fFreight).subtract(fSellerPromotionAmount)
//				.subtract(fSellerCouponAmount).subtract(fYmtCouponAmount);
//
//		return payAmount.divide(new BigDecimal(iAmount), 2,
//				BigDecimal.ROUND_HALF_UP);
//
//	}

	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_GenerateRefundCommissionInvoice_001() {
		Logger.start(true, "生成确认收货后的退货退款所引起的退佣结算单成功,单个商品全额退款");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithLogisticsType(LogisticsTypeEnum.OVERSEAS_DELIVERY);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			long tradingId = placeOrderResp.getTradingId();
			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			//支付
			Long thirdTradingId = TradingCallService.payOrder(userId,
					BigDecimal.ZERO, tradingId, "13");
			
			PayGateWayCallService.notifyCall("13",
					thirdTradingId.toString(),
					totalPrice.subtract(BigDecimal.ZERO).toString(),
					(int) userId);
			TradingSyncService.getSyncResult(orderId);
			
			Thread.sleep(5000);
			
			// 接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingSyncService.getSyncResult(orderId);
			
			// 拼邮国际段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);
			
			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);
			
			TradingCallService.confirmReceive(userId, orderId);

			Thread.sleep(5000);

			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			settlesellerincomeandchargecommissionCall.callService();

			Thread.sleep(2000);

			// 第一个商品全款退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order, 0);
			
			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行", orderId,
						i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"), "验证退货退款成功返回");
				i++;
			}
			
			Thread.sleep(4000);
			
			// 支付网关退款回调
			PayGateWayCallService.refundNotifyCall("13",
					thirdTradingId.toString(), (int) userId);

			Thread.sleep(2000);

			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Account accountInfoBeforeRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = accountInfoBeforeRefundCommition.getAvailAmount();
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			
			String refundBillNo = applyRefundReq
					.getSalesRefundInfoList().get(0).getRefundBillNo();
			
			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Account accountInfoAfterRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition.getAvailAmount();
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");
			
			RefundBillPo actualRefundBillPo = orderShardingWapper
					.selectRefundBillByBillNo(refundBillNo);

			// 退货退款单退回金额 = 申请金额-买家承担的鉴定费
			BigDecimal RefundedAmountOfCash = actualRefundBillPo
					.getTotalAmount().subtract(
							Utils.zeroIfNull(actualRefundBillPo
									.getUserAuthenticateFee()));

			int RefundProductNum = actualRefundBillPo.getProductCount(); // 可退佣金商品数量

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			
			String OrderInfoId = orderId + "000";
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());

			YmtCommissionDetail refundCommition = x.stream()
					.filter(a -> a.getInvoiceType() == 5)
					.collect(Collectors.toList()).get(0);
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			BigDecimal RealPayAmountPerProd = refundCommition
					.getRealPayAmountPerProd(); // 商品实际支付金额

			BigDecimal CommissionPerProd = refundCommition
					.getCommissionPerProd(); // 单件商品实际收佣金额
			BigDecimal SingleCommissionRate = refundCommition
					.getSingleCommissionRate(); // 退佣比例

			Logger.verifyEquals(billConmtion.getCommissionPerProd(),
					refundCommition.getCommissionPerProd(),
					"验证退佣的单个商品佣金CommissionPerProd");

			// 可退佣金商品数量=min[int（退货退款单退回金额/单件商品实际支付金额），退回数量]
			int expProdNumOfCommission = Integer.min(RefundedAmountOfCash
					.divide(RealPayAmountPerProd, BigDecimal.ROUND_DOWN)
					.intValue(), RefundProductNum);

			Logger.verifyEquals(expProdNumOfCommission,
					refundCommition.getProdNumOfCommission(),
					"验证Ymt_CommissionDetail表可退佣金商品数量");

			// 退回商品佣金= [单件商品实际收佣金额－单件商品已返佣金]×可退佣金商品数量×退佣比例
			BigDecimal expCommissionAmount = CommissionPerProd
					.multiply(new BigDecimal(expProdNumOfCommission))
					.multiply(SingleCommissionRate)
					.divide(BigDecimal.ONE, 2, BigDecimal.ROUND_HALF_UP);

			Logger.verifyEquals(expCommissionAmount,
					refundCommition.getCommissionAmount(),
					"验证Ymt_CommissionDetail表的退佣金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({P1.class})
	@TestCase
	@Ignore
	public void Tc_GenerateRefundCommissionInvoice_002() {
		Logger.start(true, "生成确认收货后的退货退款所引起的退佣结算单成功, "
				+ "单个商品部分退款小于单件商品实际支付金额, 退佣金额");
		try {

			TradingServiceResp placeOrderResp = placeOrder(true);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			// 支付订单
			TradingCallService.payOrder(userId,
					placeOrderResp.getPayableAmount(),
					placeOrderResp.getTradingId());
			// 接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingSyncService.getSyncResult(orderId);
			
			// 拼邮国际段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);
			
			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);

			TradingCallService.confirmReceive(userId, orderId);
			
			// 确认收货时生成结算单
			generateinvoicesonorderreceivedBean.setOrderId(orderId);
			generateinvoicesonorderreceivedCall
					.setData(generateinvoicesonorderreceivedBean);
			generateinvoicesonorderreceivedCall.callService();

			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			settlesellerincomeandchargecommissionCall.callService();

			// 第一个商品部分退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order, 1);
			
			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行", orderId,
						i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"), "验证退货退款成功返回");
				i++;
			}
			
			String refundBillNo = applyRefundReq.getSalesRefundInfoList().get(0).getRefundBillNo();
			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Account accountInfoBeforeRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = accountInfoBeforeRefundCommition
					.getAvailAmount();
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			generaterefundcommissioninvoiceBean.setOrderId(orderId);
			GenerateRefundCommissionInvoiceBean.ParamExt paramExt = new GenerateRefundCommissionInvoiceBean.ParamExt();
			paramExt.setRefundBillNo(refundBillNo);
			generaterefundcommissioninvoiceBean.setParamExt(paramExt);
			generaterefundcommissioninvoiceCall
					.setData(generaterefundcommissioninvoiceBean);
			generaterefundcommissioninvoiceCall.callService();
			Logger.verifyEquals("ok",
					generaterefundcommissioninvoiceCall.getReturnData(),
					"验证返回结果");
			
			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Account accountInfoAfterRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition
					.getAvailAmount();
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");
			
			String OrderInfoId = orderShardingWapper.selectUserRefundFundDetailByBizno(refundBillNo).getId();

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());
			YmtCommissionDetail refundCommition = x.stream()
					.filter(a -> a.getInvoiceType() == 5)
					.collect(Collectors.toList()).get(0);
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			Logger.verifyEquals(billConmtion.getCommissionPerProd(),
					refundCommition.getCommissionPerProd(),
					"验证退佣的单个商品佣金CommissionPerProd");
			// 部分退款，可退商品数量设置为0
			Logger.verifyEquals(0, refundCommition.getProdNumOfCommission(),
					"验证Ymt_CommissionDetail表可退佣金商品数量");
			// 部分退款，可退佣金金额为0.00
			Logger.verifyEquals(new BigDecimal(0.00).divide(new BigDecimal(1),
					2, BigDecimal.ROUND_HALF_UP), refundCommition
					.getCommissionAmount(), "验证Ymt_CommissionDetail表的退佣金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({P1.class})
	@TestCase
	@Ignore
	public void Tc_GenerateRefundCommissionInvoice_003() {
		Logger.start(true, "生成确认收货后的退货退款所引起的退佣结算单成功, 单个商品部分退款大于单件商品实际支付金额");
		try {

			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = placeOrder(true);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			// 支付订单
			TradingCallService.payOrder(userId,
					placeOrderResp.getPayableAmount(),
					placeOrderResp.getTradingId());
			// 接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingSyncService.getSyncResult(orderId);

			// 拼邮国际段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);

			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);

			TradingCallService.confirmReceive(userId, orderId);
			
			Thread.sleep(5000);
			
			// 确认收货时生成结算单
			generateinvoicesonorderreceivedBean.setOrderId(orderId);
			generateinvoicesonorderreceivedCall
					.setData(generateinvoicesonorderreceivedBean);
			generateinvoicesonorderreceivedCall.callService();
			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			settlesellerincomeandchargecommissionCall.callService();
			
			// 第一个商品全款退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order, 1);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			Thread.sleep(2000);
			
			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Account accountInfoBeforeRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = accountInfoBeforeRefundCommition
					.getAvailAmount();
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			generaterefundcommissioninvoiceBean.setOrderId(orderId);
			GenerateRefundCommissionInvoiceBean.ParamExt paramExt = new GenerateRefundCommissionInvoiceBean.ParamExt();
			String refundBillNo = applyRefundReq
					.getSalesRefundInfoList().get(0).getRefundBillNo();
			paramExt.setRefundBillNo(refundBillNo);
			generaterefundcommissioninvoiceBean.setParamExt(paramExt);
			generaterefundcommissioninvoiceCall
					.setData(generaterefundcommissioninvoiceBean);
			generaterefundcommissioninvoiceCall.callService();
			Logger.verifyEquals("ok",
					generaterefundcommissioninvoiceCall.getReturnData(),
					"验证返回结果");
			
			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Account accountInfoAfterRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition
					.getAvailAmount();
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");

			RefundBillPo actualRefundBillPo = orderShardingWapper
					.selectRefundBillByBillNo(refundBillNo);
			
			String OrderInfoId = orderShardingWapper.selectUserRefundFundDetailByBizno(refundBillNo).getId();
			BigDecimal RefundedAmountOfCash = actualRefundBillPo.getTotalAmount(); // 退货退款单退回金额

			int RefundProductNum = actualRefundBillPo.getProductCount(); // 可退佣金商品数量

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());
			YmtCommissionDetail refundCommition = x.stream()
					.filter(a -> a.getInvoiceType() == 5)
					.collect(Collectors.toList()).get(0);
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			BigDecimal RealPayAmountPerProd = refundCommition
					.getRealPayAmountPerProd(); // 单件商品实际支付金额
			BigDecimal CommissionPerProd = refundCommition
					.getCommissionPerProd(); // 单件商品实际收佣金额
			BigDecimal SingleCommissionRate = refundCommition
					.getSingleCommissionRate(); // 退佣比例

			Logger.verifyEquals(billConmtion.getCommissionPerProd(),
					refundCommition.getCommissionPerProd(),
					"验证退佣的单个商品佣金CommissionPerProd");
			// 可退佣金商品数量=min[int（退货退款单退回金额/单件商品实际支付金额），退回数量]
			int expProdNumOfCommission = Integer.min(RefundedAmountOfCash
					.divide(RealPayAmountPerProd, BigDecimal.ROUND_DOWN)
					.intValue(), RefundProductNum);
			Logger.verifyEquals(expProdNumOfCommission,
					refundCommition.getProdNumOfCommission(),
					"验证Ymt_CommissionDetail表可退佣金商品数量");
			// 退回商品佣金= [单件商品实际收佣金额－单件商品已返佣金]×可退佣金商品数量×退佣比例
			BigDecimal expCommissionAmount = CommissionPerProd
					.multiply(new BigDecimal(expProdNumOfCommission))
					.multiply(SingleCommissionRate)
					.divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_UP);
			Logger.verifyEquals(expCommissionAmount,
					refundCommition.getCommissionAmount(),
					"验证Ymt_CommissionDetail表的退佣金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@SuppressWarnings("rawtypes")
	@Test
	@Category({P1.class})
	@TestCase
	@Ignore
	// 现在都不返拥了
	public void Tc_GenerateRefundCommissionInvoice_004() {
		Logger.start(true, "老买手,老客户，生成确认收货后，已返佣金，退货退款不退拥金");
		try {
			TradingServiceResp placeOrderResp = SettlementService.placeOrder2(true);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			// 支付订单
			TradingCallService.payOrder(userId,
					placeOrderResp.getPayableAmount(),
					placeOrderResp.getTradingId());
			// 接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingSyncService.getSyncResult(orderId);

			// 拼邮国际段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);

			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);
			Thread.sleep(5000);
			
			// 确认收货时生成结算单
			generateinvoicesonorderreceivedBean.setOrderId(orderId);
			generateinvoicesonorderreceivedCall
					.setData(generateinvoicesonorderreceivedBean);
			generateinvoicesonorderreceivedCall.callService();
			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			// settlesellerincomeandchargecommissionCall.callService();

			// 第一个商品全款退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order, 0);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			Thread.sleep(2000);
			
			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Account accountInfoBeforeRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = accountInfoBeforeRefundCommition
					.getAvailAmount();
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			generaterefundcommissioninvoiceBean.setOrderId(orderId);
			GenerateRefundCommissionInvoiceBean.ParamExt paramExt = new GenerateRefundCommissionInvoiceBean.ParamExt();
			String refundBillNo = applyRefundReq
					.getSalesRefundInfoList().get(0).getRefundBillNo();
			paramExt.setRefundBillNo(refundBillNo);
			generaterefundcommissioninvoiceBean.setParamExt(paramExt);
			generaterefundcommissioninvoiceCall
					.setData(generaterefundcommissioninvoiceBean);
			generaterefundcommissioninvoiceCall.callService();
			Logger.verifyEquals("ok",
					generaterefundcommissioninvoiceCall.getReturnData(),
					"验证返回结果");
			
			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Account accountInfoAfterRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition
					.getAvailAmount();
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");
			
			// 结算表
			List<Map> settlementInvoiceList = new DefaultWapper()
					.selectYmtSettlementInvoice(orderId);

			Logger.verifyEquals(
					0,
					settlementInvoiceList
							.stream()
							.filter(commission -> (Integer) commission
									.get("BusinessType") == 5)
							.collect(Collectors.toList()).size(),
					"验证Ymt_SettlementInvoice表没有退佣结算");
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({P1.class})
	@TestCase
	@Ignore
	public void Tc_GenerateRefundCommissionInvoice_005() {
		Logger.start(true, "带运费的商品订单，确认收货后，多个商品申请退款,校验退佣结算单");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = SettlementService
					.placeOrder4(true);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			// 支付订单
			TradingCallService.payOrder(userId,
					placeOrderResp.getPayableAmount(),
					placeOrderResp.getTradingId());
			// 接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingSyncService.getSyncResult(orderId);
			
			// 拼邮国际段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);
			
			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);

			TradingCallService.confirmReceive(userId, orderId);
			
			Thread.sleep(5000);

			// 第一个商品全款退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order, 0);

			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行",
						orderId, i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"),
						"验证退货退款成功返回");
				i++;
			}

			Thread.sleep(5000);

			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			settlesellerincomeandchargecommissionCall.callService();

			Thread.sleep(2000);

			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Account accountInfoBeforeRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = accountInfoBeforeRefundCommition
					.getAvailAmount();
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			generaterefundcommissioninvoiceBean.setOrderId(orderId);

			GenerateRefundCommissionInvoiceBean.ParamExt paramExt = new GenerateRefundCommissionInvoiceBean.ParamExt();
			String refundBillNo = applyRefundReq
					.getSalesRefundInfoList().get(0).getRefundBillNo();

			paramExt.setRefundBillNo(refundBillNo);

			generaterefundcommissioninvoiceBean.setParamExt(paramExt);
			generaterefundcommissioninvoiceCall
					.setData(generaterefundcommissioninvoiceBean);
			generaterefundcommissioninvoiceCall.callService();

			Logger.verifyEquals("ok",
					generaterefundcommissioninvoiceCall.getReturnData(),
					"验证返回结果");
			SettlementService.generateRefund(applyRefundReq
					.getSalesRefundInfoList().get(1).getRefundBillNo());

			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Account accountInfoAfterRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition
					.getAvailAmount();
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");

			RefundBillPo actualRefundBillPo = orderShardingWapper
					.selectRefundBillByBillNo(refundBillNo);

			String OrderInfoId = orderShardingWapper
					.selectUserRefundFundDetailByBizno(refundBillNo).getId();
			BigDecimal RefundedAmountOfCash = actualRefundBillPo
					.getTotalAmount(); // 退货退款单退回金额

			int RefundProductNum = actualRefundBillPo.getProductCount(); // 可退佣金商品数量

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());
			YmtCommissionDetail refundCommition = x.stream()
					.filter(a -> a.getInvoiceType() == 5)
					.collect(Collectors.toList()).get(0);
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			BigDecimal RealPayAmountPerProd = refundCommition
					.getRealPayAmountPerProd(); // 单件商品实际支付金额
			BigDecimal CommissionPerProd = refundCommition
					.getCommissionPerProd(); // 单件商品实际收佣金额
			BigDecimal SingleCommissionRate = refundCommition
					.getSingleCommissionRate(); // 退佣比例

			Logger.verifyEquals(billConmtion.getCommissionPerProd(),
					refundCommition.getCommissionPerProd(),
					"验证退佣的单个商品佣金CommissionPerProd");

			// 可退佣金商品数量=min[int（退货退款单退回金额/单件商品实际支付金额），退回数量]
			int expProdNumOfCommission = Integer.min(RefundedAmountOfCash
					.divide(RealPayAmountPerProd, BigDecimal.ROUND_DOWN)
					.intValue(), RefundProductNum);

			Logger.verifyEquals(expProdNumOfCommission,
					refundCommition.getProdNumOfCommission(),
					"验证Ymt_CommissionDetail表可退佣金商品数量");
			// 退回商品佣金= [单件商品实际收佣金额－单件商品已返佣金]×可退佣金商品数量×退佣比例
			BigDecimal expCommissionAmount = CommissionPerProd
					.multiply(new BigDecimal(expProdNumOfCommission))
					.multiply(SingleCommissionRate)
					.divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_UP);
			Logger.verifyEquals(expCommissionAmount,
					refundCommition.getCommissionAmount(),
					"验证Ymt_CommissionDetail表的退佣金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({P1.class})
	@TestCase
	@Ignore
	public void Tc_GenerateRefundCommissionInvoice_006() {
		Logger.start(true, "带运费的商品订单，确认收货前退一件，确认收货后在退一件,校验退佣结算单");
		try {
			// 创建订单
			TradingServiceResp placeOrderResp = placeOrder(true);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();

			// 支付订单
			TradingCallService.payOrder(userId,
					placeOrderResp.getPayableAmount(),
					placeOrderResp.getTradingId());
			// 接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingSyncService.getSyncResult(orderId);
			
			// 拼邮国际段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 1);
			TradingSyncService.getSyncResult(orderId);
			
			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, 3);
			
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order, 1);
			
			salesrefundsuccessReq.setOrderId(orderId);

			salesrefundsuccessReq.setRefundBillNo(applyRefundReq.getSalesRefundInfoList().get(0)
					.getRefundBillNo());
			salesrefundsuccessCall.setData(salesrefundsuccessReq);

			Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行", orderId, 1));

			salesrefundsuccessCall.callService();

			Logger.verifyEquals("true",
					salesrefundsuccessCall.getString("success"), "验证退货退款成功返回");
			
			Thread.sleep(2000);

			// 确认收货
			TradingCallService.confirmReceive(userId, orderId);

			salesrefundsuccessReq.setRefundBillNo(applyRefundReq.getSalesRefundInfoList().get(1)
					.getRefundBillNo());
			salesrefundsuccessCall.setData(salesrefundsuccessReq);

			Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行", orderId, 2));

			salesrefundsuccessCall.callService();

			Logger.verifyEquals("true",
					salesrefundsuccessCall.getString("success"), "验证退货退款成功返回");

			Thread.sleep(5000);

			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			settlesellerincomeandchargecommissionCall.callService();

			Thread.sleep(2000);

			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Account accountInfoBeforeRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = accountInfoBeforeRefundCommition
					.getAvailAmount();
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			
			generaterefundcommissioninvoiceBean.setOrderId(orderId);

			GenerateRefundCommissionInvoiceBean.ParamExt paramExt = new GenerateRefundCommissionInvoiceBean.ParamExt();
			String refundBillNo = applyRefundReq
					.getSalesRefundInfoList().get(0).getRefundBillNo();

			paramExt.setRefundBillNo(refundBillNo);

			generaterefundcommissioninvoiceBean.setParamExt(paramExt);
			generaterefundcommissioninvoiceCall
					.setData(generaterefundcommissioninvoiceBean);
			generaterefundcommissioninvoiceCall.callService();

			Logger.verifyEquals("ok",
					generaterefundcommissioninvoiceCall.getReturnData(),
					"验证返回结果");

			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Account accountInfoAfterRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition
					.getAvailAmount();
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");

			RefundBillPo actualRefundBillPo = orderShardingWapper
					.selectRefundBillByBillNo(refundBillNo);

			String OrderInfoId = orderShardingWapper
					.selectUserRefundFundDetailByBizno(refundBillNo).getId();
			BigDecimal RefundedAmountOfCash = actualRefundBillPo
					.getTotalAmount(); // 退货退款单退回金额

			int RefundProductNum = actualRefundBillPo.getProductCount(); // 可退佣金商品数量

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());
			YmtCommissionDetail refundCommition = x.stream()
					.filter(a -> a.getInvoiceType() == 5)
					.collect(Collectors.toList()).get(0);
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			BigDecimal RealPayAmountPerProd = refundCommition
					.getRealPayAmountPerProd(); // 单件商品实际支付金额
			BigDecimal CommissionPerProd = refundCommition
					.getCommissionPerProd(); // 单件商品实际收佣金额
			BigDecimal SingleCommissionRate = refundCommition
					.getSingleCommissionRate(); // 退佣比例

			Logger.verifyEquals(billConmtion.getCommissionPerProd(),
					refundCommition.getCommissionPerProd(),
					"验证退佣的单个商品佣金CommissionPerProd");

			// 可退佣金商品数量=min[int（退货退款单退回金额/单件商品实际支付金额），退回数量]
			int expProdNumOfCommission = Integer.min(RefundedAmountOfCash
					.divide(RealPayAmountPerProd, BigDecimal.ROUND_DOWN)
					.intValue(), RefundProductNum);

			Logger.verifyEquals(expProdNumOfCommission,
					refundCommition.getProdNumOfCommission(),
					"验证Ymt_CommissionDetail表可退佣金商品数量");
			// 退回商品佣金= [单件商品实际收佣金额－单件商品已返佣金]×可退佣金商品数量×退佣比例
			BigDecimal expCommissionAmount = CommissionPerProd
					.multiply(new BigDecimal(expProdNumOfCommission))
					.multiply(SingleCommissionRate)
					.divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_UP);
			Logger.verifyEquals(expCommissionAmount,
					refundCommition.getCommissionAmount(),
					"验证Ymt_CommissionDetail表的退佣金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_GenerateRefundCommissionInvoice_008() {
		Logger.start(true, "买家鉴定费订单，生成确认收货后的退货退款所引起的退佣结算单成功,单个商品全额退款");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticate(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			long tradingId = placeOrderResp.getTradingId();
			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			//支付
			Long thirdTradingId = TradingCallService.payOrder(userId,
					BigDecimal.ZERO, tradingId, "13");
			
			PayGateWayCallService.notifyCall("13",
					thirdTradingId.toString(),
					totalPrice.subtract(BigDecimal.ZERO).toString(),
					(int) userId);
			TradingSyncService.getSyncResult(orderId);
			
			Thread.sleep(5000);
			
			// 接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingSyncService.getSyncResult(orderId);
			
			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 3, true);
			
			TradingCallService.confirmReceive(userId, orderId);

			Thread.sleep(5000);

			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			settlesellerincomeandchargecommissionCall.callService();

			Thread.sleep(2000);

			// 第一个商品全款退款
			ApplyRefundReq applyRefundReq = RefundService.applyRefund(order);
			
			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行", orderId,
						i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"), "验证退货退款成功返回");
				i++;
			}
			
			Thread.sleep(4000);
			
			// 支付网关退款回调
			PayGateWayCallService.refundNotifyCall("13",
					thirdTradingId.toString(), (int) userId);

			Thread.sleep(2000);

			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Account accountInfoBeforeRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = accountInfoBeforeRefundCommition.getAvailAmount();
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			
			String refundBillNo = applyRefundReq
					.getSalesRefundInfoList().get(0).getRefundBillNo();
			
			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Account accountInfoAfterRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition.getAvailAmount();
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");
			
			RefundBillPo actualRefundBillPo = orderShardingWapper
					.selectRefundBillByBillNo(refundBillNo);

			// 退货退款单退回金额 = 申请金额-买家承担的鉴定费
			BigDecimal RefundedAmountOfCash = actualRefundBillPo
					.getTotalAmount().subtract(
							Utils.zeroIfNull(actualRefundBillPo
									.getUserAuthenticateFee()));

			int RefundProductNum = actualRefundBillPo.getProductCount(); // 可退佣金商品数量

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			
			String OrderInfoId = orderId + "000";
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());

			YmtCommissionDetail refundCommition = x.stream()
					.filter(a -> a.getInvoiceType() == 5)
					.collect(Collectors.toList()).get(0);
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			BigDecimal RealPayAmountPerProd = refundCommition
					.getRealPayAmountPerProd(); // 商品实际支付金额

			BigDecimal CommissionPerProd = refundCommition
					.getCommissionPerProd(); // 单件商品实际收佣金额
			BigDecimal SingleCommissionRate = refundCommition
					.getSingleCommissionRate(); // 退佣比例

			Logger.verifyEquals(billConmtion.getCommissionPerProd(),
					refundCommition.getCommissionPerProd(),
					"验证退佣的单个商品佣金CommissionPerProd");

			// 如果但个商品的退款金额小于单个商品可支付金额，则不退佣金
			// 可退佣金商品数量=min[int（退货退款单退回金额/单件商品实际支付金额），退回数量]
			int expProdNumOfCommission = Integer.min(RefundedAmountOfCash
					.divide(RealPayAmountPerProd, BigDecimal.ROUND_DOWN)
					.intValue(), RefundProductNum);

			Logger.verifyEquals(expProdNumOfCommission,
					refundCommition.getProdNumOfCommission(),
					"验证Ymt_CommissionDetail表可退佣金商品数量");

			// 退回商品佣金= [单件商品实际收佣金额－单件商品已返佣金]×可退佣金商品数量×退佣比例
			BigDecimal expCommissionAmount = CommissionPerProd
					.multiply(new BigDecimal(expProdNumOfCommission))
					.multiply(SingleCommissionRate)
					.divide(BigDecimal.ONE, 2, BigDecimal.ROUND_HALF_UP);

			Logger.verifyEquals(expCommissionAmount,
					refundCommition.getCommissionAmount(),
					"验证Ymt_CommissionDetail表的退佣金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_GenerateRefundCommissionInvoice_009() {
		Logger.start(true, "买家鉴定费订单，退一个商品，不包含运费，生成确认收货后的退货退款所引起的退佣结算单成功");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = TradingPlaceAuthenticateCallService
					.placeOrderWithAuthenticate(
							AuthenticateFreightTypeEnum.BUYER, BigDecimal.ONE,
							AuthenticateFeeTypeEnum.BUYER, BigDecimal.TEN);

			Order order = placeOrderResp.getOrderList().get(0);

			long orderId = order.getOrderId();
			long userId = placeOrderResp.getUserId();
			long sellerId = order.getSellerId();
			long tradingId = placeOrderResp.getTradingId();
			BigDecimal totalPrice = placeOrderResp.getPayableAmount();

			//支付
			Long thirdTradingId = TradingCallService.payOrder(userId,
					BigDecimal.ZERO, tradingId, "13");
			
			PayGateWayCallService.notifyCall("13",
					thirdTradingId.toString(),
					totalPrice.subtract(BigDecimal.ZERO).toString(),
					(int) userId);
			TradingSyncService.getSyncResult(orderId);
			
			Thread.sleep(5000);
			
			// 接单
			TradingCallService.sellerAcceptOrder(sellerId, orderId);
			TradingSyncService.getSyncResult(orderId);
			
			// 拼邮国内段发货
			TradingCallService.delivery(sellerId, orderId,
					LogisticsTypeEnum.OVERSEAS_DELIVERY, "Y013", 3, true);
			
			TradingCallService.confirmReceive(userId, orderId);

			Thread.sleep(5000);

			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			settlesellerincomeandchargecommissionCall.callService();

			Thread.sleep(2000);

			// 第一个商品只退一个不带运费的商品
			ApplyRefundReq applyRefundReq = RefundService
					.buildSingleApplyRefundReq(orderId, order
							.getOrderDetailPoList().get(0), BigDecimal.ZERO, order
							.getOrderDetailPoList().get(0).getProductCount());
			
			salesrefundsuccessReq.setOrderId(orderId);

			int i = 0;

			for (SalesRefundInfoVo salesRefundInfoVo : applyRefundReq
					.getSalesRefundInfoList()) {

				salesrefundsuccessReq.setRefundBillNo(salesRefundInfoVo
						.getRefundBillNo());
				salesrefundsuccessCall.setData(salesrefundsuccessReq);

				Logger.comment(String.format("orderid: %s 第 %s 个商品 退款执行", orderId,
						i + 1));

				salesrefundsuccessCall.callService();

				Logger.verifyEquals("true",
						salesrefundsuccessCall.getString("success"), "验证退货退款成功返回");
				i++;
			}
			
			Thread.sleep(4000);
			
			// 支付网关退款回调
			PayGateWayCallService.refundNotifyCall("13",
					thirdTradingId.toString(), (int) userId);

			Thread.sleep(2000);

			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Account accountInfoBeforeRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = accountInfoBeforeRefundCommition.getAvailAmount();
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			
			String refundBillNo = applyRefundReq
					.getSalesRefundInfoList().get(0).getRefundBillNo();
			
			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Account accountInfoAfterRefundCommition = new AccountWapper()
					.selectAccountInfoByUserId((int) sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition.getAvailAmount();
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");
			
			RefundBillPo actualRefundBillPo = orderShardingWapper
					.selectRefundBillByBillNo(refundBillNo);

			// 退货退款单退回金额 = 申请金额-买家承担的鉴定费
			BigDecimal RefundedAmountOfCash = actualRefundBillPo
					.getTotalAmount().subtract(
							Utils.zeroIfNull(actualRefundBillPo
									.getUserAuthenticateFee()));

			int RefundProductNum = actualRefundBillPo.getProductCount(); // 可退佣金商品数量

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			
			String OrderInfoId = orderId + "000";
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());

			YmtCommissionDetail refundCommition = x.stream()
					.filter(a -> a.getInvoiceType() == 5)
					.collect(Collectors.toList()).get(0);
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			BigDecimal RealPayAmountPerProd = refundCommition
					.getRealPayAmountPerProd(); // 商品实际支付金额

			BigDecimal CommissionPerProd = refundCommition
					.getCommissionPerProd(); // 单件商品实际收佣金额
			BigDecimal SingleCommissionRate = refundCommition
					.getSingleCommissionRate(); // 退佣比例

			Logger.verifyEquals(billConmtion.getCommissionPerProd(),
					refundCommition.getCommissionPerProd(),
					"验证退佣的单个商品佣金CommissionPerProd");

			// 如果但个商品的退款金额小于单个商品可支付金额，则不退佣金
			// 可退佣金商品数量=min[int（退货退款单退回金额/单件商品实际支付金额），退回数量]
			int expProdNumOfCommission = Integer.min(RefundedAmountOfCash
					.divide(RealPayAmountPerProd, BigDecimal.ROUND_DOWN)
					.intValue(), RefundProductNum);

			Logger.verifyEquals(expProdNumOfCommission,
					refundCommition.getProdNumOfCommission(),
					"验证Ymt_CommissionDetail表可退佣金商品数量");

			// 退回商品佣金= [单件商品实际收佣金额－单件商品已返佣金]×可退佣金商品数量×退佣比例
			BigDecimal expCommissionAmount = CommissionPerProd
					.multiply(new BigDecimal(expProdNumOfCommission))
					.multiply(SingleCommissionRate)
					.divide(BigDecimal.ONE, 2, BigDecimal.ROUND_HALF_UP);

			Logger.verifyEquals(expCommissionAmount,
					refundCommition.getCommissionAmount(),
					"验证Ymt_CommissionDetail表的退佣金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
}
